import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  UseGuards,
  Query,
  HttpCode,
  HttpStatus,
  HttpException,
  Logger,
  NotFoundException,
  ForbiddenException,
  UnauthorizedException,
  Put,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { UpdateUserDto } from './dto/update-user.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles } from '../auth/decorators/roles.decorator';
import { UserRole } from '../common/enums';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
  ApiQuery,
} from '@nestjs/swagger';
import { UserResponseDto } from './dto/user-response.dto';
import { UpdateUserStatusDto } from './dto/update-user-status.dto';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
import { CreateUserDto } from './dto/create-user.dto';
import { ChangePasswordWithOldDto } from './dto/change-password-with-old.dto';
import { AdminResetPasswordDto } from './dto/admin-reset-password.dto';
import { UpdateMeDto } from './dto/update-me.dto';
import { JwtPayload } from '../auth/interfaces/jwt-payload.interface';

@ApiTags('User')
@Controller('users')
export class UsersController {
  private readonly logger = new Logger(UsersController.name);

  constructor(private readonly usersService: UsersService) {}

  // ==================== Admin User Management ====================

  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @Post()
  @ApiBearerAuth()
  @ApiOperation({ summary: '添加新用户 (管理员)' })
  @ApiResponse({ status: 201, description: '用户创建成功', type: UserResponseDto })
  @ApiResponse({ status: 400, description: '请求体格式错误，或字段未通过校验' })
  @ApiResponse({ status: 409, description: 'username 已存在' })
  async create(@Body() createUserDto: CreateUserDto): Promise<UserResponseDto> {
    try {
      const user = await this.usersService.createByAdmin(createUserDto);
      return user;
    } catch (error) {
      if (error.message.includes('already exists')) {
        throw new HttpException(
          {
            statusCode: HttpStatus.CONFLICT,
            message: error.message,
            error: 'Conflict',
          },
          HttpStatus.CONFLICT,
        );
      }
      throw error;
    }
  }

  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @Get()
  @ApiBearerAuth()
  @ApiOperation({ summary: '获取用户列表（仅管理员）' })
  @ApiResponse({
    status: 200,
    description: '用户列表',
    schema: {
      type: 'object',
      properties: {
        data: {
          type: 'array',
          items: { $ref: '#/components/schemas/UserResponseDto' },
        },
        pagination: {
          type: 'object',
          properties: {
            total: { type: 'number', example: 100 },
            page: { type: 'number', example: 1 },
            pageSize: { type: 'number', example: 10 },
          },
        },
      },
    },
  })
  @ApiQuery({ name: 'page', required: false, description: '页码，从1开始', type: Number })
  @ApiQuery({ name: 'limit', required: false, description: '每页数量', type: Number })
  @ApiQuery({
    name: 'search',
    required: false,
    description: '搜索关键词（用户名、显示名）',
    type: String,
  })
  @ApiQuery({
    name: 'role',
    required: false,
    description: '按用户角色过滤',
    enum: UserRole,
  })
  @ApiQuery({
    name: 'isActive',
    required: false,
    description: '按用户激活状态过滤',
    type: Boolean,
  })
  @ApiQuery({
    name: 'createdAfter',
    required: false,
    description: '注册时间范围（大于等于）',
    type: String,
  })
  @ApiQuery({
    name: 'deviceSerialNumber',
    required: false,
    description: '按设备序列号过滤',
    type: String,
  })
  async findAll(
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 10,
    @Query('search') search?: string,
    @Query('role') role?: UserRole,
    @Query('isActive') isActive?: string,
    @Query('createdAfter') createdAfter?: string,
    @Query('deviceSerialNumber') deviceSerialNumber?: string,
  ): Promise<{
    data: UserResponseDto[];
    pagination: { total: number; page: number; pageSize: number };
  }> {
    const isActiveBoolean = isActive ? isActive === 'true' : undefined;

    const result = await this.usersService.findAll({
      page,
      limit,
      search,
      role,
      isActive: isActiveBoolean,
      createdAfter,
      deviceSerialNumber,
    });

    return {
      data: result.items,
      pagination: {
        total: result.meta.total,
        page: Number(result.meta.page),
        pageSize: Number(result.meta.limit),
      },
    };
  }

  @UseGuards(JwtAuthGuard)
  @Get('me')
  @ApiBearerAuth()
  @ApiOperation({ summary: '获取当前用户信息' })
  @ApiResponse({ status: 200, description: '用户信息' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  async getMe(@CurrentUser() currentUser: JwtPayload) {
    this.logger.log(`Getting profile for user ID: ${currentUser.userId}`);

    // Get full user details from database
    const user = await this.usersService.findById(currentUser.userId);
    if (!user) {
      throw new NotFoundException('User not found5');
    }

    // Return user information using the service's getMe method
    return this.usersService.getMe(user);
  }

  @UseGuards(JwtAuthGuard, RolesGuard)
  @Patch('me')
  @ApiBearerAuth()
  @ApiOperation({ summary: '更新当前用户信息' })
  @ApiResponse({ status: 200, description: '更新成功', type: UserResponseDto })
  @ApiResponse({ status: 400, description: '请求体格式错误，或字段未通过校验' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: '无权限访问此资源' })
  async updateMe(
    @Body() updateMeDto: UpdateMeDto,
    @CurrentUser() currentUser: JwtPayload,
  ): Promise<UserResponseDto> {
    this.logger.log(`Updating profile for user ID: ${currentUser.userId}`);

    // Update user information using the restricted DTO
    const updatedUser = await this.usersService.update(
      currentUser.userId,
      updateMeDto,
      false, // Not admin operation
    );

    this.logger.log(`Profile updated successfully for user ID: ${currentUser.userId}`);
    return updatedUser;
  }

  @UseGuards(JwtAuthGuard)
  @Put('me/password')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiBearerAuth()
  @ApiOperation({ summary: '使用旧密码更改密码' })
  @ApiResponse({ status: 204, description: '密码更改成功' })
  @ApiResponse({ status: 401, description: 'Unauthorized 或旧密码不正确' })
  async changePasswordWithOld(
    @Body() changePasswordDto: ChangePasswordWithOldDto,
    @CurrentUser() currentUser: JwtPayload,
  ) {
    this.logger.log(`Password change requested for user ID: ${currentUser.userId}`);

    try {
      await this.usersService.changePassword(
        currentUser.userId,
        changePasswordDto.oldPassword,
        changePasswordDto.newPassword,
      );

      this.logger.log(`Password changed successfully for user ID: ${currentUser.userId}`);
    } catch (error) {
      this.logger.error(`Password change failed for user ID: ${currentUser.userId}`, error.stack);

      if (error.message === 'Current password is incorrect') {
        throw new UnauthorizedException('Current password is incorrect');
      }

      throw error;
    }
  }

  @UseGuards(JwtAuthGuard)
  @Get(':userId')
  @ApiBearerAuth()
  @ApiOperation({ summary: '获取用户详情' })
  @ApiResponse({ status: 200, description: '用户详情', type: UserResponseDto })
  @ApiResponse({ status: 404, description: '用户不存在' })
  @ApiParam({ name: 'userId', description: '用户ID', type: String })
  findOne(@Param('userId') userId: string) {
    return this.usersService.findOne(userId);
  }

  @UseGuards(JwtAuthGuard)
  @Patch(':userId')
  @ApiBearerAuth()
  @ApiOperation({ summary: '更新用户信息' })
  @ApiResponse({ status: 200, description: '更新成功', type: UserResponseDto })
  @ApiResponse({ status: 403, description: '无权限修改' })
  @ApiResponse({ status: 404, description: '用户不存在' })
  @ApiParam({ name: 'userId', description: '用户ID', type: String })
  async update(
    @Param('userId') userId: string,
    @Body() updateUserDto: UpdateUserDto,
    @CurrentUser() currentUser: JwtPayload,
  ): Promise<UserResponseDto> {
    this.logger.log(`Updating user info for user ID: ${userId}`);

    // Verify the user exists
    const user = await this.usersService.findById(userId);
    if (!user) {
      this.logger.warn(`User not found with ID: ${userId}`);
      throw new NotFoundException('User not found6');
    }

    // Only allow users to update their own profile or admins to update any profile
    if (currentUser.userId !== userId && currentUser.role !== UserRole.ADMIN) {
      this.logger.warn(`User ${currentUser.userId} attempted to update profile of user ${userId}`);
      throw new ForbiddenException('You can only update your own profile');
    }

    // Update user information
    const updatedUser = await this.usersService.update(
      userId,
      updateUserDto,
      currentUser.role === UserRole.ADMIN,
    );

    this.logger.log(`User info updated successfully for user ID: ${userId}`);
    return updatedUser;
  }

  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @Patch(':userId/status')
  @ApiBearerAuth()
  @ApiOperation({ summary: '更新用户状态（仅管理员）' })
  @ApiResponse({ status: 200, description: '更新成功', type: UserResponseDto })
  @ApiResponse({ status: 404, description: '用户不存在' })
  @ApiParam({ name: 'userId', description: '用户ID', type: String })
  updateStatus(
    @Param('userId') userId: string,
    @Body() updateUserStatusDto: UpdateUserStatusDto,
  ): Promise<UserResponseDto> {
    return this.usersService.updateStatus(userId, updateUserStatusDto);
  }

  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @Delete(':userId')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiBearerAuth()
  @ApiOperation({ summary: '删除用户（仅管理员）' })
  @ApiResponse({ status: 204, description: '删除成功' })
  @ApiResponse({ status: 404, description: '用户不存在' })
  @ApiParam({ name: 'userId', description: '用户ID', type: String })
  async remove(@Param('userId') userId: string) {
    await this.usersService.remove(userId);
  }

  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @Put(':userId/password')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiBearerAuth()
  @ApiOperation({ summary: '管理员重置用户密码（无需旧密码）' })
  @ApiResponse({ status: 204, description: '密码已重置' })
  @ApiResponse({ status: 403, description: '不允许修改管理员账户密码（超级管理员除外）' })
  @ApiParam({ name: 'userId', description: '用户ID', type: String })
  async resetPassword(
    @Param('userId') userId: string,
    @Body() adminResetPasswordDto: AdminResetPasswordDto,
  ) {
    this.logger.log(`Admin password reset requested for user ID: ${userId}`);

    try {
      await this.usersService.resetPasswordByAdmin(
        userId,
        adminResetPasswordDto.newPassword,
        adminResetPasswordDto.forceLogout,
      );

      this.logger.log(`Password reset successfully for user ID: ${userId}`);
    } catch (error) {
      this.logger.error(`Password reset failed for user ID: ${userId}`, error.stack);
      throw error;
    }
  }
}
